<template>
  <div class="params-container">
    <!-- 面包屑导航 -->
    <el-breadcrumb separator-class="el-icon-arrow-right">
      <el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item>
      <el-breadcrumb-item>商品管理</el-breadcrumb-item>
      <el-breadcrumb-item>商品参数</el-breadcrumb-item>
    </el-breadcrumb>
    <!-- 卡片区域 -->
    <el-card class="box-card">
      <!-- 提示文本 -->
      <el-alert
        title="注意：只能对三级分类设置相关参数"
        :closable="false"
        show-icon
        type="warning">
      </el-alert>
      <!-- 级联选择器 -->
      <el-row>
        <el-col>
          <span>选择商品分类：</span>
          <el-cascader
            v-model="currentCates"
            :options="cateList"
            :props="listProps"
            clearable
            @change="cascaderChange"></el-cascader>
        </el-col>
      </el-row>
      <!-- 静态、动态信息选择页签菜单 -->
      <el-tabs v-model="activeName" @tab-click="tabsChange">
        <el-tab-pane label="静态属性" name="only">
          <el-button type="info" :disabled="btnDisabled" @click="showonlyDialog">添加属性</el-button>
          <el-table :data="onlyParams" stripe border>
            <el-table-column type="expand">
              <!-- 作用域插槽绑定的scope就是table中绑定的data属性manyParams -->
              <template slot-scope="scope">
                <!-- 静态参数值tag -->
                <!-- 循环scope的当前行数据的属性值属性 -->
                <!-- <el-tag v-for="(item, i) in scope.row.attr_vals" :key="i">{{item}}</el-tag> -->
                <el-tag
                  :key="i"
                  v-for="(tag, i) in scope.row.attr_vals"
                  closable
                  :disable-transitions="false"
                  @close="attrTagClose(tag, scope.row)">
                  {{tag}}
                </el-tag>
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.newTagValue"
                  ref="saveTagInput"
                  size="small"
                  @blur="attrTagAdding(scope.row)"
                >
                </el-input>
                <el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
              </template>
            </el-table-column>
            <el-table-column type="index" label="#"></el-table-column>
            <el-table-column prop="attr_name" label="属性名称"></el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button type="primary" icon="el-icon-edit" round size=mini @click="editOnly(scope.row)">编辑</el-button>
                <el-button type="danger" icon="el-icon-delete" round size=mini @click="deleteBothParams(scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
          <!-- 添加静态属性对话框 -->
          <el-dialog
            title="添加静态属性"
            :visible.sync="onlyDialogVisible"
            width="50%"
            @closed="onlyDialogClosed">
            <!-- 静态属性表单区域 -->
            <el-form :model="onlyForm" ref="onlyFormRef" :rules="onlyFormRules">
              <el-form-item label="静态属性" label-width="100px" prop="attr_name">
                <el-input v-model="onlyForm.attr_name"></el-input>
              </el-form-item>
            </el-form>
            <!-- 下方确认区域 -->
            <span slot="footer" class="dialog-footer">
              <el-button @click="onlyDialogClosed">取 消</el-button>
              <el-button type="primary" @click="submitOnlyForm">确 定</el-button>
            </span>
          </el-dialog>
          <!-- 修改静态属性对话框 -->
          <el-dialog
            title="修改静态属性"
            :visible.sync="editOnlyDialogVisible"
            width="50%"
            @closed="editOnlyDialogClosed">
            <!-- 修改静态属性表单区域 -->
            <el-form :model="editOnlyForm" ref="editOnlyFormRef" :rules="editOnlyFormRules">
              <el-form-item label="静态属性" label-width="100px" prop="attr_name">
                <el-input v-model="editOnlyForm.attr_name"></el-input>
              </el-form-item>
            </el-form>
            <!-- 下方确认区域 -->
            <span slot="footer" class="dialog-footer">
              <el-button @click="editOnlyDialogClosed">取 消</el-button>
              <el-button type="primary" @click="submitEditOnly">确 定</el-button>
            </span>
          </el-dialog>
        </el-tab-pane>

        <el-tab-pane label="动态参数" name="many">
          <el-button type="info" :disabled="btnDisabled" @click="showManyDialog">添加参数</el-button>
          <el-table :data="manyParams" stripe border>
            <el-table-column type="expand">
              <!-- 作用域插槽绑定的scope就是table中绑定的data属性manyParams -->
              <template slot-scope="scope">
                <!-- 动态属性值tag -->
                <!-- 循环scope的当前行数据的属性值属性 -->
                <!-- <el-tag v-for="(item, i) in scope.row.attr_vals" :key="i">{{item}}</el-tag> -->
                <el-tag
                  :key="i"
                  v-for="(tag, i) in scope.row.attr_vals"
                  closable
                  :disable-transitions="false"
                  @close="attrTagClose(tag, scope.row)">
                  {{tag}}
                </el-tag>
                <el-input
                  class="input-new-tag"
                  v-if="scope.row.inputVisible"
                  v-model="scope.row.newTagValue"
                  ref="saveTagInput"
                  size="small"
                  @blur="attrTagAdding(scope.row)"
                >
                </el-input>
                <el-button v-else class="button-new-tag" size="small" @click="showInput(scope.row)">+ New Tag</el-button>
              </template>
            </el-table-column>
            <el-table-column type="index" label="#"></el-table-column>
            <el-table-column prop="attr_name" label="参数名称"></el-table-column>
            <el-table-column label="操作">
              <template slot-scope="scope">
                <el-button type="primary" icon="el-icon-edit" round size=mini @click="editMany(scope.row)">编辑</el-button>
                <el-button type="danger" icon="el-icon-delete" round size=mini @click="deleteBothParams(scope.row)">删除</el-button>
              </template>
            </el-table-column>
          </el-table>
          <!-- 添加动态参数的对话框 -->
          <el-dialog
            title="添加动态参数"
            :visible.sync="manyDialogVisible"
            width="50%"
            @closed="manyDialogClosed">
            <!-- 添加动态参数表单区域 -->
            <el-form :model="manyForm" ref="manyFormRef" :rules="manyFormRules">
              <el-form-item label="动态参数" label-width="100px" prop="attr_name">
                <el-input v-model="manyForm.attr_name"></el-input>
              </el-form-item>
            </el-form>
            <!-- 下方确认区域 -->
            <span slot="footer" class="dialog-footer">
              <el-button @click="manyDialogClosed">取 消</el-button>
              <el-button type="primary" @click="submitManyForm">确 定</el-button>
            </span>
          </el-dialog>
          <!-- 修改动态参数对话框 -->
          <el-dialog
            title="修改动态参数"
            :visible.sync="editManyDialogVisible"
            width="50%"
            @closed="editManyDialogClosed">
            <!-- 修改动态参数表单区域 -->
            <el-form :model="editManyForm" ref="editManyFormRef" :rules="editManyFormRules">
              <el-form-item label="动态参数" label-width="100px" prop="attr_name">
                <el-input v-model="editManyForm.attr_name"></el-input>
              </el-form-item>
            </el-form>
            <!-- 下方确认区域 -->
            <span slot="footer" class="dialog-footer">
              <el-button @click="editManyDialogClosed">取 消</el-button>
              <el-button type="primary" @click="submitEditMany">确 定</el-button>
            </span>
          </el-dialog>

        </el-tab-pane>
      </el-tabs>
    </el-card>
  </div>
</template>

<script>
import { getParentCate } from '@/api/getCateListApi.js'
import { getCateAttri } from '@/api/getCateAttriApi.js'
import { addParams, addAttr } from '@/api/addParamsApi.js'
import { changeParams } from '@/api/changeParamsApi.js'
import { deleteParams } from '@/api/deleteParamsApi.js'
export default {
  name: 'myParams',
  data () {
    return {
      // 存放分类信息的数组
      cateList: [],
      // 级联选择器当前选中的元素及其父元素的id的数组
      currentCates: [],
      // 级联选择器配置属性
      listProps: {
        expandTrigger: 'hover',
        label: 'cat_name',
        value: 'cat_id',
        children: 'children'
      },
      // 选中页签的名称
      // 由于后端"参数列表"接口中存在sel参数用于判断请求"参数列表"的类型
      // 所以本变量同时决定发送请求时参数是only还是many
      activeName: 'only',
      // 存放静态属性的数组
      onlyParams: [],
      // 静态属性表单
      onlyForm: {
        // 静态属性名
        attr_name: '',
        attr_sel: 'only'
      },
      // 存放动态参数的数组
      manyParams: [],
      // 动态参数表单
      manyForm: {
        // 动态参数名
        attr_name: '',
        // 请求类型：动态参数
        attr_sel: 'many',
        // 动态参数选项值
        attr_vals: ''
      },
      // 动态参数表单校验规则
      manyFormRules: {
        attr_name: [{ required: true, message: '请输入参数名', trigger: 'blur' }]
      },
      // 静态属性表单校验规则
      onlyFormRules: {
        attr_name: [{ required: true, message: '请输入参数名', trigger: 'blur' }]
      },
      // 添加动态参数对话框显隐控件
      manyDialogVisible: false,
      // 添加静态属性对话框显隐控件
      onlyDialogVisible: false,

      // 修改静态属性对话框的显隐控件
      editOnlyDialogVisible: false,
      // 修改静态属性对话框的表单对象
      editOnlyForm: {
        // 静态属性名
        attr_name: '',
        attr_sel: 'only',
        cat_id: 0,
        attr_id: 0
      },
      // 修改静态属性对话框的表单验证对象
      editOnlyFormRules: {
        attr_name: [{ required: true, message: '请输入参数名', trigger: 'blur' }]
      },

      // 修改动态参数对话框的显隐控件
      editManyDialogVisible: false,
      // 修改动态参数对话框的表单对象
      editManyForm: {
        // 动态参数名
        attr_name: '',
        attr_sel: 'many',
        attr_vals: '',
        cat_id: 0,
        attr_id: 0
      },
      // 修改动态参数对话框的表单验证对象
      editManyFormRules: {
        attr_name: [{ required: true, message: '请输入参数名', trigger: 'blur' }]
      }
    }
  },
  methods: {
    async getParents () {
      const { data: res } = await getParentCate(3)
      if (res.meta.status !== 200) {
        return this.$notify.error({ title: '获取分类信息失败', message: res.meta.msg })
      }
      // 否则获取成功，存入catelist
      this.cateList = res.data
    },
    // 获取当前分类的参数列表
    async getCateAttributes () {
      // 请求对应分类的参数列表
      const { data: res } = await getCateAttri(this.currentCate, this.activeName)
      // 防止用户删除选中项时弹出错误提示
      if (res.meta.status !== 200 && this.currentCates.length !== 0) {
        return this.$notify.error({ title: '获取参数列表失败', message: res.meta.msg })
      }
      // 否则获取成功，根据activeName的不同来决定数据源变量
      if (this.activeName === 'only') {
        // 切分静态参数的attr_vals值
        for (const i in res.data) {
          const staticVals = res.data[i].attr_vals.split(' ')
          staticVals.forEach(element => {
            if (element === '') {
              staticVals.splice(staticVals.indexOf(element), 1)
            }
          })
          res.data[i].attr_vals = staticVals
          // 添加tag显隐控制变量与input表单值变量
          res.data[i].inputVisible = false
          res.data[i].newTagValue = ''
        }
        this.onlyParams = res.data
        console.log(this.onlyParams)
      } else {
        // 如果是动态参数，则需要将atrr_var字符串属性中的内容按空格切分，存入一个数组中
        for (const i in res.data) {
          // console.log(res.data[i])
          // res.data[i]是每个动态参数对象，里面存放着参数id、名称、值等属性
          // 对其中的值属性进行切分，获得属性值数组
          // 将属性值切分数组更新为数组类型
          const valsArr = res.data[i].attr_vals.split(' ')
          for (const j in valsArr) {
            if (valsArr[j] === '') {
              // console.log(valsArr[j])
              valsArr.splice(valsArr[j], 1)
            }
          }
          res.data[i].attr_vals = valsArr
          // 向源数据中添加控制tag显隐的变量以及表单值变量
          res.data[i].inputVisible = false
          res.data[i].newTagValue = ''
        }
        /** 可以使用forEach遍历数组对象
         * res.data.forEach(item => {
         *  item.attr_vals = item.attr_vals.split(' ')
         * })
         * */
        // 将修改后的接口返回数组赋值给manyParams数组
        this.manyParams = res.data
      }
    },
    // 添加参数post函数
    async addBothParams (form) {
      const { data: res } = await addParams(this.currentCate, form)
      if (res.meta.status !== 201) {
        return this.$notify.error({ title: '新增失败', message: res.meta.msg })
      }
      // 否则新增成功
      this.$notify.success({ title: '新增成功' })
    },

    // 级联选择器选中属性改变的事件处理函数
    cascaderChange () {
      this.getCateAttributes()
    },
    // 卡片中的导航菜单的事件处理函数
    tabsChange () {
      // 触发该事件后需要使用新的activeName参数发起对参数列表的请求
      this.getCateAttributes()
    },
    // 添加动态参数的对话框
    showManyDialog () {
      this.manyDialogVisible = true
    },
    // 展示添加静态属性对话框
    showonlyDialog () {
      this.onlyDialogVisible = true
    },
    // 添加动态参数对话框关闭
    manyDialogClosed () {
      // 清除表单验证和输入信息
      this.$refs.manyFormRef.resetFields()
      this.manyDialogVisible = false
    },
    // 添加静态属性对话框关闭
    onlyDialogClosed () {
      // 清除表单信息
      this.$refs.onlyFormRef.resetFields()
      this.onlyDialogVisible = false
    },
    // 添加静态属性对话框确定事件
    submitOnlyForm () {
      // 表单验证，通过再发起请求
      this.$refs.onlyFormRef.validate(cb => {
        if (!cb) {
          return this.$notify.error({ title: '表单校验未通过', message: cb })
        }
        // 否则校验通过过，调用addBothParams发起请求
        this.addBothParams(this.onlyForm)
        // 请求成功后重新初始化当前分类的属性列表
        this.getCateAttributes()
        // 最后隐藏对话框
        this.onlyDialogVisible = false
      })
    },
    // 添加动态属性对话框确定事件
    submitManyForm () {
      // 表单验证，通过再发起请求
      this.$refs.manyFormRef.validate(cb => {
        if (!cb) {
          return this.$notify.error({ title: '表单校验未通过', message: cb })
        }
        // 否则校验通过过，调用addBothParams发起请求
        this.addBothParams(this.manyForm)
        // 请求成功后重新初始化当前分类的属性列表
        this.getCateAttributes()
        // 最后隐藏对话框
        this.manyDialogVisible = false
      })
    },

    // 修改静态属性按钮的点击事件
    editOnly (row) {
      // 将选中的参数名、分类id、参数id存入修改静态属性表单对象中
      this.editOnlyForm.attr_name = row.attr_name
      this.editOnlyForm.attr_id = row.attr_id
      this.editOnlyForm.cat_id = row.cat_id
      this.editOnlyForm.attr_vals = row.attr_vals
      // 显示对话框
      this.editOnlyDialogVisible = true
    },
    // 修改动态参数按钮的点击事件
    editMany (row) {
      // 将选中的参数名、分类id、参数id存入修改动态参数表单对象中
      this.editManyForm.attr_name = row.attr_name
      this.editManyForm.attr_id = row.attr_id
      this.editManyForm.cat_id = row.cat_id
      this.editManyForm.attr_vals = row.attr_vals
      // 显示对话框
      this.editManyDialogVisible = true
    },
    // 取消修改操作事件
    editOnlyDialogClosed () {
      // 初始化表单
      this.$refs.editOnlyFormRef.resetFields()
      // 关闭对话框
      this.editOnlyDialogVisible = false
    },
    editManyDialogClosed () {
      // 初始化表单
      this.$refs.editManyFormRef.resetFields()
      // 关闭对话框
      this.editManyDialogVisible = false
    },
    // 提交修改操作事件
    submitEditOnly () {
      // 验证表单是否合法
      this.$refs.editOnlyFormRef.validate(async cb => {
        if (!cb) {
          return this.$notify.error({ title: '表单校验失败', message: cb })
        }
        // 否则校验成功，发起请求
        const { data: res } = await changeParams(this.editOnlyForm)
        console.log(res)
        if (res.meta.status !== 200) {
          return this.$notify.error({ title: '修改失败', message: res.meta.msg })
        }
        // 否则成功，初始化参数列表
        this.$notify.success({ title: '修改成功' })
        this.getCateAttributes()
        // 隐藏对话框
        this.editOnlyDialogVisible = false
      })
    },
    submitEditMany () {
      // 验证表单是否合法
      this.$refs.editManyFormRef.validate(async cb => {
        if (!cb) {
          return this.$notify.error({ title: '表单校验失败', message: cb })
        }
        // 否则校验成功，现在editManyForm表单中参数值以数组形式存储，需要修改为字符串
        this.editManyForm.attr_vals = this.editManyForm.attr_vals.join(' ')
        // 格式修改完成后发起请求
        const { data: res } = await changeParams(this.editManyForm)
        if (res.meta.status !== 200) {
          return this.$notify.error({ title: '修改失败', message: res.meta.msg })
        }
        // 否则成功，初始化参数列表
        this.$notify.success({ title: '修改成功' })
        this.getCateAttributes()
        // 隐藏对话框
        this.editManyDialogVisible = false
      })
    },
    // 删除按钮点击事件
    async deleteBothParams (row) {
      const result = await this.$confirm('将永久移除该参数，是否继续？', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).catch(err => err)
      if (result !== 'confirm') {
        // 取消操作
        return this.$notify.info({ title: '已取消操作' })
      }
      // 否则删除参数
      const { data: res } = await deleteParams(row.cat_id, row.attr_id)
      if (res.meta.status !== 200) {
        return this.$notify.error({ title: '删除失败', message: res.meta.msg })
      }
      // 否则删除成功
      this.$notify.success({ title: '删除成功' })
      // 重新加载参数列表
      this.getCateAttributes()
    },
    // 动态属性值tags的关闭事件
    async attrTagClose (tag, row) {
      // 删除本条属性值，即从row的attr_vals属性中删除tag
      // 数组按值删除可使用array.splice(array.indexOf('xxx'), 1)
      row.attr_vals.splice(row.attr_vals.indexOf(tag), 1)
      // 将删除后的数组join为空格分割的字符串，作为参数传给后端
      const { data: res } = await addAttr(row, row.attr_vals.join(' '))
      if (res.meta.status !== 200) { return this.$notify.error({ title: '删除失败，请刷新页面', message: res.meta.msg }) }
      // 否则删除成功，同理于下面新增tag，不用手动刷新数据
      this.$notify.success({ title: '删除成功' })
    },
    // 动态属性新增tag的确定事件
    async attrTagAdding (row) {
      console.log(row)
      // 判断输入值是否合法
      if (row.newTagValue.trim() === '') {
        return this.$notify.error({ title: '请输入属性值' })
      }
      // 否则不为空，将新属性值写入数据库
      row.attr_vals.push(row.newTagValue)
      // 新增临时变量存放属性值
      let newAttrArray = row.attr_vals
      // 将该临时变量数组Join为字符串，作为参数传给后端
      newAttrArray = newAttrArray.join(' ')
      // 发起put请求
      const { data: res } = await addAttr(row, newAttrArray)
      if (res.meta.status !== 200) {
        return this.$notify.error({ title: '新增失败', message: res.meta.msg })
      }
      // 否则请求成功
      /**
       * 由于新属性先添加到作用域插槽中
       * scope属性的当前行属性row的attr_vals属性中，
       * 故页面在没有手动请求新数据的情况下依然会将新的属性值展示出来
       * 同时后端已经将新属性值存在数据库中，下次刷新页面会请求完整属性数据
       * 将属性值从字符串split成数组，故下次打开本页面展示的也是新的属性数据
       * 所以这里不用请求新的参数数据
       */
      this.$notify.success({ title: '新增成功' })
      // 清空newTagValue的值
      row.newTagValue = ''
      // 隐藏输入框
      row.inputVisible = false
    },
    // + new tag按钮的点击事件
    showInput (row) {
      // 显示输入框，隐藏按钮
      row.inputVisible = true
      console.log(row.newTagValue)
      // 调用nextTick()函数，在dom元素更新之后获取输入框的焦点
      this.$nextTick(_ => {
        // saveTagInput为el-input的ref属性值
        this.$refs.saveTagInput.$refs.input.focus()
      })
    }
  },
  computed: {
    btnDisabled () {
      // 若tabs下的按钮需要被禁用则返回true
      if (this.currentCates.length !== 0) return false
      else return true
    },
    currentCate () {
      return this.currentCates[this.currentCates.length - 1]
    }
  },
  created () {
    this.getParents()
  }
}
</script>

<style lang="less" scoped>
  .el-alert {
    margin-bottom: 20px;
  }
  .el-tabs {
    margin-top: 10px;
  }
  .el-table {
    margin-top: 20px;
  }
  .el-tag {
    margin-left:12px;
  }
  .input-new-tag {
    width: 90px;
    margin-left: 12px;
    vertical-align: bottom;
  }
  .button-new-tag {
    margin-left: 12px;
  }
</style>
